package com.letoken.platform.app.consumer;

import com.letoken.platform.pub.enums.LetokenTokenTypeEnum;
import com.letoken.platform.pub.enums.TokenTransactionStatusEnum;
import com.letoken.platform.pub.enums.TokenTransactionTypeEnum;
import com.letoken.platform.repo.app.dao.AppUserWalletMapper;
import com.letoken.platform.repo.app.dao.RedEnvelopeMoneysMapper;
import com.letoken.platform.repo.app.dao.RedEnvelopesMapper;
import com.letoken.platform.repo.app.po.AppUserAssetsHistory;
import com.letoken.platform.repo.app.po.AppUserWallet;
import com.letoken.platform.repo.app.po.RedEnvelope;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.CustomExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
@RabbitListener()
@RestController
public class RedEnvelopeReturnConsumer {

    public final static String exchange = "letoken.red_envelope_return";
    public final static String routingKey = "red_envelope.return";
    private final static String queue = "red_envelope.return";

    @Bean
    public Queue redEnvelopeReturnQueue() {
        return new Queue(queue);
    }

    @Bean
    public CustomExchange redEnvelopeReturnExchange() {
        //第一种设置方法  设置延迟交换机配置
        Map<String, Object> args = new HashMap<>();
        //设置交换机支持延迟消息推送
        args.put("x-delayed-type", "direct");
        return new CustomExchange(exchange, "x-delayed-message", false, true, args);
    }

    @Bean
    public Binding lazyBinding(@Qualifier("redEnvelopeReturnExchange") CustomExchange redEnvelopeReturnExchange, @Qualifier("redEnvelopeReturnQueue") Queue redEnvelopeReturnQueue) {
        return BindingBuilder.bind(redEnvelopeReturnQueue).to(redEnvelopeReturnExchange).with(routingKey).noargs();
    }

    @Resource
    private RedEnvelopeMoneysMapper redEnvelopeMoneysMapper;

    @Resource
    private RedEnvelopesMapper redEnvelopesMapper;

    @Resource
    private AppUserWalletMapper appUserWalletMapper;

    @Resource
    private PlatformTransactionManager transactionManager;


    @RabbitListener(queues = queue)
    @RabbitHandler
    public void redEnvelopeReturnConsumer(@Payload int id) {
        doReturn(id);
    }

    public void doReturn(int id) {
        RedEnvelope redEnvelope;
        BigDecimal remainingMoney;
        AppUserWallet appUserWalletUpdate;
        TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            redEnvelope = redEnvelopesMapper.selectForUpdate(id);
            if (null == redEnvelope || 2 == redEnvelope.getStatus() || 3 == redEnvelope.getStatus()) {
                transactionManager.commit(transactionStatus);
                return;
            }
            remainingMoney = redEnvelopeMoneysMapper.sumByInfoId(redEnvelope.getId());

            AppUserWallet appUserWallet = appUserWalletMapper.selectForUpdate2(redEnvelope.getOwner(), 2);
            appUserWalletUpdate = new AppUserWallet();
            appUserWalletUpdate.setAvailableBalance(appUserWallet.getAvailableBalance().add(remainingMoney));
            appUserWalletUpdate.setId(appUserWallet.getId());
            appUserWalletUpdate.updateById();

            RedEnvelope redEnvelopeUpdate = new RedEnvelope();
            redEnvelopeUpdate.setStatus(3);
            redEnvelopeUpdate.setId(redEnvelope.getId());
            redEnvelopeUpdate.updateById();

            AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
            assetHistory.setUserId(redEnvelope.getOwner());
            assetHistory.setType(TokenTransactionTypeEnum.RED_ENVELOPE_RETURN.getValue());
            assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
            assetHistory.setTokenId(2);
            assetHistory.setAmount(remainingMoney);
            assetHistory.setBalance(appUserWalletUpdate.getAvailableBalance());
            assetHistory.setCreateTime(LocalDateTime.now());
            assetHistory.insert();

            transactionManager.commit(transactionStatus);
        } catch (Exception e) {
            transactionManager.rollback(transactionStatus);
            log.error("error to return red envelope;id=" + id, e);
        }

    }


}